/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jgaptest;

import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;

/**
 *
 * @author Claudio
 */
public class Operations {

    public static int OR = 0;
    public static int AND = 1;
    public static int XOR = 2;
    public static int XNOR = 3;
    public static int NOT = 4;
    public static int ADD = 5;
//    private int width = 0;
//    private int height = 0;
    public static final float[] square = new float[]{
        1, 1, 1,
        1, 1, 1,
        1, 1, 1
    };
    public static final float[] circle5 = new float[]{
        -1, 1, 1, 1, -1,
        1, 1, 1, 1, 1,
        1, 1, 1, 1, 1,
        1, 1, 1, 1, 1,
        -1, 1, 1, 1, -1
    };
    public static final float[] circle = new float[]{
        -1, 1, -1,
        1, 1, 1,
        -1, 1, -1
    };
    public static final float[] ldiag = new float[]{
        1, -1, -1,
        -1, 1, -1,
        -1, -1, 1
    };
    public static final float[] rdiag = new float[]{
        -1, -1, 1,
        -1, 1, -1,
        1, -1, -1
    };
    public static final float[] vertic = new float[]{
        1, 1, 1
    };
    public static final float[] horiz = new float[]{
        1, 1, 1
    };

    private double getConvVal(float[] kernel, int w, int h, int kw, int kh, WritableRaster raster, int x, int y) {
        float res = 0;
        int h_w = Math.abs(kw / 2);
        int h_h = Math.abs(kh / 2);
        int cnt = 0;
        for (int i = -1 * h_w; i < h_w + 1; i++) {
            for (int j = -1 * h_h; j < h_h + 1; j++) {
                //for (int kw = 0; kw < kernellX.length; kw++) {
                if (x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                    continue;
                }
                res += raster.getSample(x + i, y + j, 0) * kernel[cnt];
                cnt++;
                //}
            }
        }
        return res;
    }

    public static int[][] erode(float[] kernel, int kw, int kh, int w, int h, int[][] orig, int[][] dest, int th, boolean binary) {

//        WritableRaster raster2 = dest.getRaster();
//        WritableRaster raster = orig.getRaster();
//        int w = raster.getWidth();
//        int h = raster.getHeight();
        int h_w = Math.abs(kw / 2);
        int h_h = Math.abs(kh / 2);
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                int cnt = 0;
                if (orig[x][y] > 0) {
                    //double ret = getConvVal(kernel, w, h, 5, 5, raster, x, y);
                    cnt = 0;
                    loop:
                    for (int i = -1 * h_w; i < h_w + 1; i++) {
                        for (int j = -1 * h_h; j < h_h + 1; j++) {
                            //for (int kw = 0; kw < kernellX.length; kw++) {
                            if (kernel[cnt] < 0 || x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                                //raster2.setSample(x, y, 0, 1);
                                cnt++;
                                continue;
                            } else if (orig[x + i][y + j] == 0) {
                                //raster2.setSample(x, y, 0, 0);
                                dest[x][y] = 0;
                                cnt = 0;
                                continue loop;
                            }
                            cnt++;
                            //}
                        }
                    }

                    if (cnt == kw * kh) {
                        dest[x][y] = 255;
                    }
                    cnt = 0;
                }
            }
        }
        return dest;
    }

    public static int[][] erodeGrey(float[] kernel, int kw, int kh, int w, int h, int[][] orig) {
        int[][] dest = new int[w][h];
//        WritableRaster raster2 = dest.getRaster();
//        WritableRaster raster = orig.getRaster();
//        int w = raster.getWidth();
//        int h = raster.getHeight();
        int h_w = Math.abs(kw / 2);
        int h_h = Math.abs(kh / 2);
        int sum;
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                int cnt = 0;
                if (orig[x][y] > 0) {
                    //double ret = getConvVal(kernel, w, h, 5, 5, raster, x, y);
                    cnt = 0;
                    //loop:
                    sum = 255;
                    //loop:
                    for (int i = -1 * h_w; i < h_w + 1 && sum > 0; i++) {
                        for (int j = -1 * h_h; j < h_h + 1 && sum > 0; j++) {
                            if (kernel[cnt] < 0 || x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                                cnt++;
                                continue;
                            } else {// if (raster.getSample(x + i, y + j, 0) == 0) {
                                sum = Math.min(orig[x + i][y + j], sum);
                            }
                            cnt++;
                        }
                    }
                    cnt = 0;
                    if (sum > 0) {
                        cnt = 0;
                    }

                    for (int i = -1 * h_w; i < h_w + 1; i++) {
                        for (int j = -1 * h_h; j < h_h + 1; j++) {
                            //for (int kw = 0; kw < kernellX.length; kw++) {
                            if (kernel[cnt] < 0 || x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                                //raster2.setSample(x, y, 0, 1);
                                cnt++;
                                continue;
                            } else {// if (raster.getSample(x + i, y + j, 0) == 0) {
                                dest[x + i][y + j] = sum;
                                //cnt = 0;
                                //continue loop;
                            }
                            cnt++;
                            //}
                        }
                    }
                    cnt = 0;
                }
            }
        }
        return dest;
    }

    public static int[][] dilate(float[] kernel, int kw, int kh, int w, int h, int[][] orig, int[][] dest) {

//        WritableRaster raster2 = dest.getRaster();
//        WritableRaster raster = orig.getRaster();
//        int w = raster.getWidth();
//        int h = raster.getHeight();
        int h_w = Math.abs(kw / 2);
        int h_h = Math.abs(kh / 2);
        int sum = 0;
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                dest[x][y] = orig[x][y];
                //raster2.setSample(x, y, 0, raster.getSample(x, y, 0));

                if (orig[x][y] > 0) {
                    //double ret = getConvVal(kernel, w, h, 5, 5, raster, x, y);
                    int cnt = 0;
                    sum = 0;
                    loop:
                    for (int i = -1 * h_w; i < h_w + 1; i++) {
                        for (int j = -1 * h_h; j < h_h + 1; j++) {
                            //for (int kw = 0; kw < kernellX.length; kw++) {
                            if (kernel[cnt] < 0 || x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                                cnt++;
                                continue;
                            } else if (orig[x + i][y + j] == 0) {
                                orig[x + i][y + j] = 255;
                                //continue loop;
                                //cnt = 1;
                            }
                            cnt++;
                            //}
                        }
                    }

                }
            }
        }
        return dest;
    }

    public static int[][] dilateGrey(float[] kernel, int kw, int kh, int w, int h, int[][] orig) {
        int[][] dest = new int[w][h];
//        WritableRaster raster2 = dest.getRaster();
//        WritableRaster raster = orig.getRaster();
//        int w = raster.getWidth();
//        int h = raster.getHeight();
        int h_w = Math.abs(kw / 2);
        int h_h = Math.abs(kh / 2);
        int sum = 0;
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                //raster2.setSample(x, y, 0, raster.getSample(x, y, 0));
                dest[x][y] = orig[x][y];

                if (orig[x][y] > 0) {
                    //double ret = getConvVal(kernel, w, h, 5, 5, raster, x, y);
                    int cnt = 0;
                    sum = 0;
                    //loop:
                    for (int i = -1 * h_w; i < h_w + 1; i++) {
                        for (int j = -1 * h_h; j < h_h + 1; j++) {
                            if (kernel[cnt] < 0 || x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                                cnt++;
                                continue;
                            } else {//if (raster.getSample(x + i, y + j, 0) == 0) {
                                sum = Math.max(orig[x + i][y + j], sum);
                            }
                            cnt++;
                        }
                    }
                    cnt = 0;
                    for (int i = -1 * h_w; i < h_w + 1; i++) {
                        for (int j = -1 * h_h; j < h_h + 1; j++) {
                            //for (int kw = 0; kw < kernellX.length; kw++) {
                            if (kernel[cnt] < 0 || x + i < 0 || x + i >= w || y + j < 0 || y + j >= h) {
                                cnt++;
                                continue;
                            } else {// if (raster.getSample(x + i, y + j, 0) == 0) {
                                //raster2.setSample(x + i, y + j, 0, sum);
                                dest[x + i][y + j] = sum;
                                //continue loop;
                                //cnt = 1;
                            }
                            cnt++;
                            //}
                        }
                    }

                }
            }
        }
        return dest;
    }

    public static int[][] logical(int[][] orig1, int[][] orig2,int w, int h, int operator) {
        int[][] dest = new int[w][h];
//        WritableRaster ro1 = orig1.getRaster();
//        WritableRaster ro2 = orig2.getRaster();
//        WritableRaster rd = dest.getRaster();
        int width = w;//orig1.getWidth();
        int height = h;//orig1.getHeight();
        int v1;
        int v2;
        int max = 0;
        int min;
        int res = 0;
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                v1 = orig1[i][j];
                v2 = orig2[i][j];
                max = Math.max(v1, v2);
                min = Math.min(v1, v2);
                if (operator == Operations.XOR) {
                    res = Math.max(0, Math.min(255, (v1 ^ v2) & 0xff));
                } else if (operator == Operations.AND) {
                    res = Math.max(0, Math.min(255, (v1 & v2) & 0xff));
                } else if (operator == Operations.OR) {
                    res = Math.max(0, Math.min(255, (v1 | v2) & 0xff));
                } else if (operator == Operations.XNOR) {
                    res = Math.max(0, Math.min(255, ~(v1 ^ v2) & 0xff));
                } else if (operator == Operations.NOT) {
                    res = Math.max(0, Math.min(255, ~(v1) & 0xff));
                } else if (operator == Operations.ADD) {
                    res = Math.max(0, Math.min(255, v1 + v2));
                }
                dest[i][j] = res;

            }
        }
        return dest;
    }

    public static int[][] loadData(BufferedImage img) {
        WritableRaster ro1 = img.getRaster();
        int[][] data = new int[img.getWidth()][img.getHeight()];
        for (int i = 0; i < img.getWidth(); i++) {
            for (int j = 0; j < img.getHeight(); j++) {
                data[i][j] = ro1.getSample(i, j, 0);
            }
        }
        return data;
    }

    public static int distancia(int[][] a, int[][] b, int w, int h) {
        int dist = 0;
        for (int i = 0; i < w; i++) {
            for (int j = 0; j < h; j++) {
                dist += Math.abs(a[i][j] - b[i][j]);
            }
        }
        return dist / (w * h);
    }
}